package cn.com.libertymutual.sys.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReadDataThead implements Runnable {
	
	private Logger log = LoggerFactory.getLogger(getClass());
	
	private SelectionKey key;
	private Map<SelectionKey, FileChannel> fileMap;
	
	public ReadDataThead( SelectionKey key, Map<SelectionKey, FileChannel> fileMap ) {
		this.key = key;
		this.fileMap = fileMap;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		ByteBuffer buffer = ByteBuffer.allocate(1024 * 512);  
        FileChannel fileChannel = null;	///fileMap.get(key);  
        buffer.clear();  

        SocketChannel socketChannel = (SocketChannel) key.channel();  
        int num = 0;
        try {
        	if( fileMap.containsKey(key) ) {
        		fileChannel = fileMap.get(key);
        	}
        	else {
        		ReadFileData read = new ReadFileData();
        	
        		fileChannel = read.getFileChannel(socketChannel);
        	}
        	
            while ((num = socketChannel.read(buffer)) > 0) {
                buffer.flip();
                //写入文件 
                fileChannel.write(buffer);
                buffer.clear();
            }
        } catch (Exception e) {
        	
        	fileMap.remove(key);
        	
            key.cancel();
            e.printStackTrace();
            log.error("传输错误:{}", e.getMessage());

            try {
            	if( fileChannel != null )
            		fileChannel.close();
            	
				socketChannel.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
            return;  
        }
        // 调用close为-1 到达末尾  
        if (num == -1) {
            try {
            	if( fileChannel != null )
            		fileChannel.close();
            	
                log.info("上传完毕");
                buffer.clear();
                //buffer = ByteBuffer.allocate(32);
                //buffer.put();  
                //buffer.clear();ByteBuffer.wrap( (socketChannel.getRemoteAddress() + "上传成功").getBytes() );
                socketChannel.write( ByteBuffer.wrap( (socketChannel.getRemoteAddress() + "上传成功").getBytes() ) );
                socketChannel.close();
            } catch (IOException e) {
                e.printStackTrace();  
            }
            
            fileMap.remove(key);
            
            // 只有调用cancel才会真正从已选择的键的集合里面移除，否则下次select的时候又能得到  
            // 一端close掉了，其对端仍然是可读的，读取得到EOF，返回-1  
            key.cancel();
            return;  
        }
        else {
        	if( !fileMap.containsKey(key) )
        		fileMap.put(key, fileChannel);
        }
        // Channel的read方法可能返回0，返回0并不一定代表读取完了。  
        // 工作线程结束对通道的读取，需要再次更新键的ready集合，将感兴趣的集合重新放在里面  
        key.interestOps(key.interestOps() | SelectionKey.OP_READ);  
        // 调用wakeup，使得选择器上的第一个还没有返回的选择操作立即返回即重新select  
        key.selector().wakeup();

	}

}